﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ChongJu.Camera;
using ChongJu.EventManager;
using ChongJu.GlobalInfo;
using ChongJu.ImageAnalyze;
using ChongJu.ModelManager.Rating;
using ChongJu.ModelManager;
using Public.Logger;
using Public.MvvmBase;
using Public.Tools;
using System.Collections.ObjectModel;
using GalaSoft.MvvmLight.Threading;
using System.Threading;
using System.Windows;
using ChongJu.CloudService;
using System.IO;
using System.Windows.Media;
using ChoJu.Single.DAL;
using Microsoft.Practices.Prism.Commands;
using ChoJuRating.View;
using ChoJu.Single.Views;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using ChoJu.ModelManager.Config;
using ChongJu.ModelManager.MQTT;
using ChoJu.GlobalInfo;
using System.Diagnostics;

namespace ChoJu.Single.ViewModel
{
    public class RatingVM : PropertyChangedBase
    {
        /// <summary>
        /// 委托定义，用于控制界面元素
        /// </summary>
        public delegate void ScrollToEnd();
        public ScrollToEnd FocusLastItem = null;

        private CloudService _cloud;

        //UI实时显示图片的数据流
        private MemoryStream _stream = null;

        private WindowVoice _voice;

        private UploadDal _uploadDal;

        private ViewRatingMsg _viewRatingMsg;

        private bool _isBusy = false;

        private bool _isUp = false; //是否是上层图片

        private Stopwatch _sw = new Stopwatch();

        public RatingVM()
        {
            Camera.Instance.ImageCallBackEvent += this.Instance_ImageCallBackEvent;
            CommonEvent.RunLoggerEventReport += CommonEvent_RunLoggerEventReport;
            CommonEvent.SystemCommandEventReport += CommonEvent_SystemCommandEventReport;

            ClearCommand = new DelegateCommand(ClearFunction);
            //WeightCommand = new DelegateCommand(WeightFunnction);

            _cloud = new CloudService();
            RunLogs = new ObservableCollection<RunLogModel>();
            _voice = new WindowVoice();
            _uploadDal = new UploadDal();

            _viewRatingMsg = new ViewRatingMsg();
            MsgContent = _viewRatingMsg;

            if (GlobalVar.GlobalParamer.IsBottom == true)
                _isUp = false;
            else
                _isUp = true;

            Task.Run(() => Init());

            if (GlobalVar.GlobalParamer.IsWeight == true)
                Task.Run(() => GetWerght());
        }


        public object MsgContent
        {
            get { return _msgContent; }
            set { _msgContent = value; OnPropertyChanged(() => MsgContent); }
        }
        private object _msgContent;


        public string ResultMsg
        {
            get { return _resultMsg; }
            set { _resultMsg = value; OnPropertyChanged(() => ResultMsg); }
        }
        private string _resultMsg;


        /// <summary>
        /// 当前烟叶图片
        /// </summary>
        public object CurrentImage
        {
            get { return _currentImage; }
            set { _currentImage = value; OnPropertyChanged(() => CurrentImage); }
        }
        private object _currentImage;

        /// <summary>
        /// 下层图片
        /// </summary>
        public object DownImage
        {
            get { return _downImage; }
            set { _downImage = value; OnPropertyChanged(() => DownImage); }
        }
        private object _downImage;


        /// <summary>
        /// 处理图片数
        /// </summary>
        public int ImageCount
        {
            get { return _imageCount; }
            set { _imageCount = value; OnPropertyChanged(() => ImageCount); }
        }
        private int _imageCount;


        /// <summary>
        /// 接收图片数
        /// </summary>
        public int TriggerCount
        {
            get { return _triggerCount; }
            set { _triggerCount = value; OnPropertyChanged(() => TriggerCount); }
        }
        private int _triggerCount;

        /// <summary>
        /// 异常信号数
        /// </summary>
        public int ExceptionCount
        {
            get { return _exceptionCount; }
            set { _exceptionCount = value; OnPropertyChanged(() => ExceptionCount); }
        }
        private int _exceptionCount;

        /// <summary>
        /// 运行日志
        /// </summary>
        public ObservableCollection<RunLogModel> RunLogs
        {
            get { return _runLogs; }
            set { _runLogs = value; OnPropertyChanged(() => RunLogs); }
        }
        private ObservableCollection<RunLogModel> _runLogs;


        public string TipMessage
        {
            get { return _tipMessage; }
            set { _tipMessage = value; OnPropertyChanged(() => TipMessage); }
        }
        private string _tipMessage = "初始化中……";


        public int AverageTime
        {
            get { return _averageTime; }
            set { _averageTime = value; OnPropertyChanged(() => AverageTime); }
        }
        private int _averageTime;

        public long WeightDeal
        {
            get { return _weightDeal; }
            set { _weightDeal = value; OnPropertyChanged(() => WeightDeal); }
        }
        private long _weightDeal;

        public long ImageDeal
        {
            get { return _imageDeal; }
            set { _imageDeal = value; OnPropertyChanged(() => ImageDeal); }
        }
        private long _imageDeal;

        /// <summary>
        /// 料仓烟叶数量
        /// </summary>
        public StoreCountModel StoreCount
        {
            get
            {
                if (_storeCount == null)
                    _storeCount = new StoreCountModel();
                return _storeCount;
            }
            set { _storeCount = value; OnPropertyChanged(() => StoreCount); }
        }
        private StoreCountModel _storeCount;


        public string ViewRating
        {
            get { return _viewRating; }
            set { _viewRating = value; OnPropertyChanged(() => ViewRating); }
        }
        private string _viewRating;


        public double CurrentWeight
        {
            get { return _currentWeight; }
            set { _currentWeight = value; OnPropertyChanged(() => CurrentWeight); }
        }
        private double _currentWeight;



        public DelegateCommand ClearCommand { get; }

        public DelegateCommand WeightCommand { get; }

        private void Instance_ImageCallBackEvent(Bitmap image, DateTime time)
        {
            if (GlobalVar.CurrentRunType != RunTypeEnum.None)
                return;

            _isBusy = true;
            QueueAnaylze(image, _isUp);

            if (GlobalVar.GlobalParamer.IsBottom == true)
            {
                if (_isUp == true)
                {
                    _isUp = false;
                    Camera.Instance.Stop();
                    Camera.Instance.OpneLine1CloseLine2();
                    Camera.Instance.Start();
                    Camera.Instance.SetTriggerByLine0();
                }
                else
                {
                    _isUp = true;
                    Camera.Instance.Stop();
                    Camera.Instance.OpneLine2CloseLine1();
                    Camera.Instance.Start();
                    Camera.Instance.SetTriggerBySoftware();
                    Camera.Instance.TakeOne();
                }
            }
        }

        /// <summary>
        /// 多线程解析图片
        /// </summary>
        /// <param name="image"></param>
        private void QueueAnaylze(Bitmap image, bool isUp)
        {
            DateTime curTime = DateTime.Now;
            try
            {

                TriggerCount++;
                var imgInfo = new ImageIndexModel()
                {
                    IsUp = isUp,
                    ReceiveImageTime = curTime,
                    Guid = Tool.GuidTo16String(),
                    ImageDetail = new RatingResultModel()
                    {
                        Image = image,
                        ImageData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, image.PixelFormat)
                    },
                };

                imgInfo.ReadWeightTime = DateTime.Now;

                ImageAnaylze(imgInfo);
            }
            catch (Exception ex)
            {
                Logger.Error("接收图片异常：", ex);
            }
            finally
            {
            }
        }

        /// <summary>
        /// 解析图片
        /// </summary>
        /// <param name="imgInfo"></param>
        private void ImageAnaylze(ImageIndexModel imgInfo)
        {
            Task.Factory.StartNew(() =>
            {
                try
                {
                    //分选模式
                    //1、解析等级信息
                    //2、发动等级信息到PLC  落框
                    //3、根据采样率保存原始图片
                    //Logger.Debug($"===={imgInfo.Guid}开始解析时间为：{DateTime.Now.ToString("HHmmssfff")}=={Tool.DateTimeToLong(DateTime.Now)}");
                    imgInfo.AnayzeStartTime = DateTime.Now;
                    _sw.Restart();
                    if (GlobalVar.GlobalParamer.IsWeight == true)
                        imgInfo.ImageDetail.Weight = GlobalVar.GlobalParamer.WeightType != 1 ? (float)SerialPortDal.Instance.GetWeight() : (float)WeightDal.Instance.GetWeight();
                    _sw.Stop();
                    WeightDeal = _sw.ElapsedMilliseconds;

                    _sw.Restart();
                    var lev = AnalyzeService.Instance.TaskAnalyze(imgInfo.ImageDetail.Image, imgInfo.ImageDetail.ImageData, imgInfo.ImageDetail.Weight, isUp:imgInfo.IsUp);
                    _sw.Stop();
                    ImageDeal = _sw.ElapsedMilliseconds;
                    
                    imgInfo.AnayzeEndTime = DateTime.Now;
                    _isBusy = false;

                    if (imgInfo.IsUp == false & lev == null)
                        return;

                    if (lev == null)
                    {
                        CommonEvent.OnRunLogger($"=异常信号= 处理失败");
                        imgInfo.SendPLCTime = DateTime.Now;
                        imgInfo.SendPLCEndTime = DateTime.Now;
                        ExceptionCount++;
                        ViewImageUI(imgInfo.ImageDetail.Image, 1);
                        return;
                    }

                    AverageTime = (int)imgInfo.DealTotalTime;
                    CreateRunLog($"{lev.Rating}类  {lev.RatingCode} {imgInfo.ImageDetail.Weight}");
                    CreateRunLog($"{ImageDeal} {WeightDeal} {AverageTime}");

                    if (lev.RatingName.ToLower().StartsWith("cx") == true)
                        ResultMsg = "杂烟";
                    else if (lev.RatingName.ToLower().StartsWith("gy") == true)
                        ResultMsg = "青烟";
                    else if (lev.RatingCode.ToLower().StartsWith("na") == true)
                        ResultMsg = GlobalVar.GlobalParamer.NaTipMessage;
                    else
                        ResultMsg = lev.Rating + "类";
                    _voice.Send(ResultMsg);

                    if (lev.RatingCode.ToLower().StartsWith("na") == false)
                        ImageCount++;
                    else
                        ExceptionCount++;

                    if (string.IsNullOrEmpty(lev.RatingName) == false &
                        lev.RatingCode.ToLower().StartsWith("na") == false)
                        _uploadDal.SendInfo(lev.RatingName);

                    //CreateRunLog(tm.ToString());
                    SetCount(lev.Rating);
                    ViewImageUI(imgInfo.ImageDetail.Image, 1);
                }
                catch (Exception ex)
                {
                    Logger.Error("解析图片异常", ex);
                }
                finally
                {
                    //_logService.AddRunLog(imgInfo.LogJson);
                }
            });
        }

        private void Init()
        {
            try
            {
                CreateRunLog("-----初始化-----");
                if (GlobalVar.SiteInfo == null)
                {
                    GlobalVar.SiteInfo = _cloud.SearchSiteInfo(GlobalVar.DeviceID, out var isRe);
                    if (isRe == true)
                    {
                        _cloud.RegistDevice(GlobalVar.DeviceID);
                        MessageBox.Show("待后台确认注册信息");
                        return;
                    }

                    if (string.IsNullOrEmpty(GlobalVar.SiteInfo?.SiteCode) == false)
                    {
                        CreateRunLog("获取站点信息 成功");
                        InitModel.SiteInfo = true;
                    }
                    else
                        CreateRunLog("获取站点信息 失败");
                }
                else
                    InitModel.SiteInfo = true;

                if (InitModel.Model == false && InitModel.SiteInfo == true)
                {
                    InitModel.Model = AnalyzeService.Instance.InitModel(GlobalVar.SiteInfo);
                    if (InitModel.Model == false)
                        CreateRunLog("初始化模型失败");
                    else
                        CreateRunLog("初始化模型成功");
                }

                if (InitModel.Camera == false)
                {
                    //初始化相机
                    InitModel.Camera = Camera.Instance.Init(_cloud);
                    if (InitModel.Camera == true)
                    {
                        CreateRunLog("初始化相机成功");
                        Thread.Sleep(1000);
                        InitModel.Camera = Camera.Instance.Open();
                        if (InitModel.Camera == true)
                            CreateRunLog("打开相机成功");
                        else
                            CreateRunLog("打开相机失败");

                        //Camera.Instance.TakeOne();
                    }
                    else
                        CreateRunLog("初始化相机失败");
                }

                if(InitModel.Weight == false & GlobalVar.GlobalParamer.IsWeight == true)
                {
                    var cfg = LiteDBClient.Instance.Get<WeightConfigModel>(ConfigType.Weight);
                    InitModel.Weight = GlobalVar.GlobalParamer.WeightType != 1 ? SerialPortDal.Instance.Init(cfg) : WeightDal.Instance.Init(cfg);
                    if(InitModel.Weight == true)
                        CreateRunLog("称重初始化成功");
                    else
                        CreateRunLog("称重初始化失败");
                }

                if (InitModel.Complate == true)
                {
                    CreateRunLog("--- 初始化 完成 ---");
                    TipMessage = "设备准备完成";
                    GlobalVar.CurrentRunType = RunTypeEnum.None;
                }
            }
            catch (Exception ex)
            {

            }
            finally
            {
                if (InitModel.Complate == false)
                {
                    Thread.Sleep(1500);
                    Init();
                }
            }
        }

        private void CreateRunLog(string log)
        {
            DispatcherHelper.CheckBeginInvokeOnUI(() =>
            {
                RunLogs.Add(new RunLogModel() { Message = log, Time = DateTime.Now });
                if (RunLogs.Count > 1000)
                {
                    var lst = RunLogs.ToList();
                    lst.RemoveRange(20, 500);
                    RunLogs = new ObservableCollection<RunLogModel>(lst);
                }

                OnPropertyChanged(() => RunLogs);
                FocusLastItem();
            });

        }

        private void ViewImageUI(Bitmap image, int index)
        {
            //image = Tool.RotateImageBy90Degrees(image);
            Task.Factory.StartNew(() =>
            {
                try
                {
                    if (_stream != null)
                        _stream.Dispose();

                    _stream = new MemoryStream();
                    var compress = new SaveImage().ImageCompress(image);
                    if (compress == null)
                        return;

                    compress.Save(_stream, ImageFormat.Png);
                    DispatcherHelper.CheckBeginInvokeOnUI(() =>
                    {
                        try
                        {
                            CurrentImage = (ImageSource)new ImageSourceConverter().ConvertFrom(_stream);

                            compress?.Dispose();
                            image?.Dispose();
                        }
                        catch (Exception ex)
                        {
                            Logger.Error("UI显示图片异常,内部调用", ex);
                        }
                    });

                    if (GlobalVar.CurrentRunType == RunTypeEnum.Collection)
                    {
                        var path = Path.Combine(AppContext.BaseDirectory, "Image_temp");
                        if (Directory.Exists(path) == false)
                            Directory.CreateDirectory(path);

                        var file = Path.Combine(path, DateTime.Now.ToString("yyyyMMddhhssmm") + ".png");
                        image.Save(file);
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error("UI显示图片异常", ex);
                }
                finally
                {
                    image?.Dispose();
                }
            });
        }

        private void CommonEvent_RunLoggerEventReport(string obj)
        {
            CreateRunLog(obj);
        }

        private void ClearFunction()
        {
            if (CJMsgBox.ShowDialog("是否清空日志信息", viewCancel: true) == false)
                return;

            RunLogs.Clear();
            OnPropertyChanged(() => RunLogs);
            ViewRating = string.Empty;

            TriggerCount = ImageCount = ExceptionCount = AverageTime = 0;
            StoreCount = new StoreCountModel();
        }

        private void CommonEvent_SystemCommandEventReport(MqttCommandModel cmd)
        {
            if (cmd?.DeviceID != GlobalVar.DeviceID)
                return;

            switch (cmd.Type)
            {
                case CommandEnum.Model: RefreshModel(); break;
                case CommandEnum.UploadConfigFiles: UploadConfigAsync();break;
                case CommandEnum.Config: DownLoadConfigAsync();break;
            }
        }

        private void RefreshModel()
        {
            //先获取站点信息
            var siteInfo = _cloud.SearchSiteInfo(GlobalVar.DeviceID, out var isRe);
            if (siteInfo == null)
                return;

            //二次加载模型
            var bol = AnalyzeService.Instance.InitModel(siteInfo);
            if (bol == true)
            {
                GlobalVar.SiteInfo = siteInfo;
                CreateRunLog("加载模型成功");
            }
            else
            {
                CreateRunLog("加载模型失败");
            }
        }

        private void UploadConfigAsync()
        {
            _cloud.UploadConfigFiles(GlobalVar.DeviceID);
        }

        private void DownLoadConfigAsync()
        {
            var dirRoot = Path.Combine(AppContext.BaseDirectory, "Config");
            var url = $"{Tool.GetConfig("api")}/config/download?deviceID={GlobalVar.DeviceID}";
            var response = HttpReqest.Get(url);
            var result = Tool.JsonToObject<ResponseMode>(response);
            if(result?.Code != ErrorCodeEnum.Success)
            {
                Logger.Debug("下载配置文件失败");
                return;
            }

            var configs = Tool.JsonToObject<List<ConfigSaveModel>>(result?.Data?.ToString());
            if(configs?.Count > 0 == false)
            {
                Logger.Debug("没有配置文件");
                return;
            } 

            foreach(var config in configs)
            {
                var file = Path.Combine(dirRoot, config.Name);
                File.WriteAllText(file, config.Content);
            }
        }

        private void SetCount(int index)
        {
            switch (index)
            {
                case 1: StoreCount.One += 1; break;
                case 2: StoreCount.Two += 1; break;
                case 3: StoreCount.Three += 1; break;
                case 4: StoreCount.Four += 1; break;
                case 5: StoreCount.Five += 1; break;
                case 6: StoreCount.Six += 1; break;
                case 7: StoreCount.Seven += 1; break;
                case 8: StoreCount.Eight += 1; break;
                case 9: StoreCount.Nine += 1; break;
                case 10: StoreCount.Ten += 1; break;
                case 11: StoreCount.Eleven += 1; break;
                case 12: StoreCount.Twelve += 1; break;
            }

            StoreCount = StoreCount;
        }

        private void GetWerght()
        {
            CurrentWeight = WeightDal.Instance.CurrentWeight;
            Thread.Sleep(100);
            GetWerght();
        }
    }

    public class SaveImage
    {
        /// <summary>
        /// 保存原始图片
        /// </summary>
        /// <param name="level"></param>
        /// <param name="image"></param>
        /// <returns></returns>
        public string SaveOrigin(RatingResultModel level, Bitmap image, bool taskSave = true)
        {
            try
            {
                var dirPath = Path.Combine(ConfigFileInfo.ImageOriginPathConfig,
                    DateTime.Now.ToString("yyyyMMdd"),
                    level.BatchID.ToString(),
                    level.RatingName);

                if (Directory.Exists(dirPath) == false)
                    Directory.CreateDirectory(dirPath);

                var file = Path.Combine(dirPath, $"{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.png");
                if (taskSave == true)
                    Tool.SaveBitmap(image, file, false);
                else
                    image.Save(file, ImageFormat.Png);

                return file;
            }
            catch (Exception ex)
            {
                Logger.Error("保存原始图片异常：", ex);
                return null;
            }
            finally
            {
                if (taskSave == false)
                    image?.Dispose();
            }
        }

        /// <summary>
        ///  @Deprecated
        /// 保存压缩图片
        /// 保存完之后释放压缩图片所占用的内存，但是对原图不做处理
        /// </summary>
        /// <param name="level"></param>
        /// <param name="image"></param>
        /// <returns></returns>
        public string SaveCompress(Bitmap image)
        {
            Bitmap tempImg = null;
            try
            {
                var dirPath = Path.Combine(ConfigFileInfo.ImageTempPathConfig,
                DateTime.Now.ToString("yyyyMMdd"));

                if (Directory.Exists(dirPath) == false)
                    Directory.CreateDirectory(dirPath);

                var file = Path.Combine(dirPath, $"{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.jpg");

                var height = (int)(1.0 * ConfigFileInfo.RESIZE_IMAGE_WIDTH / ConfigFileInfo.RESIZE_IMAGE_WIDTH * ConfigFileInfo.RESIZE_IMAGE_HEIGHT);
                tempImg = new Bitmap(image, ConfigFileInfo.RESIZE_IMAGE_WIDTH, height);
                tempImg.Save(file, ImageFormat.Jpeg);
                tempImg.Dispose();

                //tempImg = new Bitmap(image, image.Width, image.Height);
                //var eps = new EncoderParameters(1);
                //var ep = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality,30L);
                //eps.Param[0] = ep;
                //var jpsEncodeer = GetEncoder(ImageFormat.Jpeg);
                //tempImg.Save(file, jpsEncodeer, eps);

                return file;
            }
            catch (Exception ex)
            {
                Logger.Error("保存压缩图片异常：", ex);
                return null;
            }
            finally
            {
                tempImg?.Dispose();
            }
        }

        public Bitmap ImageCompress(Bitmap image)
        {
            Bitmap tempImg = null;
            try
            {
                var height = (int)(1.0 * ConfigFileInfo.RESIZE_IMAGE_WIDTH / ConfigFileInfo.RESIZE_IMAGE_WIDTH * ConfigFileInfo.RESIZE_IMAGE_HEIGHT);
                tempImg = new Bitmap(image, ConfigFileInfo.RESIZE_IMAGE_WIDTH, height);
                return tempImg;
            }
            catch (Exception ex)
            {
                Logger.Error("压缩图片异常：", ex);
                return null;
            }
        }

        public ImageCodecInfo GetEncoder(ImageFormat format)
        {
            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
            foreach (ImageCodecInfo codec in codecs)
            {
                if (codec.FormatID == format.Guid)
                    return codec;
            }
            return null;
        }
    }
}
